package com.hss.cls

/**
 * Created by Administrator on 2017/6/6.
 */
//主构造器 (primary constructor), 以及一个或多个 次构造器 (secondary
//constructor). 主构造器是类头部的一部分, 位于类名称(以及可选的类型参数)之后.
//主构造器中不能包含任何代码. 初始化代码可以放在 初始化代码段 (initializer block) 中, 初始化代码段使用
//init 关键字作为前缀:

class Person constructor(firstName:String){
    val children :Array<Person4> = arrayOf()
    val name = ""
    init {
//        lo.info("Customer initialized with value ${name}")
    }
}
//如果主构造器没有任何注解(annotation), 也没有任何可见度修饰符, 那么 constructor 关键字可以省略:
class Person1(firstName:String){
    val customerKey = firstName.toUpperCase()
}

class Person2(val firstName: String, val lastName: String, var age: Int) {
// ...
}

//如果构造器有注解, 或者有可见度修饰符, 这时 constructor 关键字是必须的, 注解和修饰符要放在它之前:
/*
class Person3 public @Inject constructor(name: String) {
}
*/
//次级构造器 (secondary constructor), 使用 constructor 关键字作为前缀:
class Person4 {
    constructor(parent: Person) {
//        parent.children.add(this)
    }

}
//    如果类有主构造器, 那么每个次级构造器都必须委托给主构造器, 要么直接委托, 要么通过其他次级构造器
//    间接委托. 委托到同一个类的另一个构造器时, 使用 this 关键字实现:

    class Person5(val name: String) {
        constructor(name: String, parent: Person) : this(name) {
//            parent.children.add(this)
        }
    }

//    如果一个非抽象类没有声明任何主构造器和次级构造器, 它将带有一个自动生成的, 无参数的主构造器. 这
//    个构造器的可见度为 public. 如果不希望你的类带有 public 的构造器, 你需要声明一个空的构造器, 并明确
//    设置其可见度:
class DontCreateMe private constructor () {

}


//在 JVM 中, 如果主构造器的所有参数都指定了默认值, 编译器将会产生一个额外的无参数构造
//器, 这个无参数构造器会使用默认参数值来调用既有的构造器. 有些库(比如 Jackson 或 JPA) 会使用无
//参数构造器来创建对象实例, 这个特性将使得 Kotlin 比较容易与这种库协同工作.
open class Customer(val customerName: String = ""){
    open fun v(){}
    fun nv() {}

    open var x :Int
      get() {
          return x
      }
       set(value) {
           x = value
       }

    open  var pname = "lisi"
     get() {
         return pname
     }
}

val  per = Person("zhangsan")
//注意, Kotlin 没有 new 关键字.

//Kotlin 中所有的类都有一个共同的超类 Any , 如果类声明时没有指定超类, 则默认为 Any :
//尤其要注意, 除
// equals() ,
// hashCode() 和
// toString() 之外,
// 它没有任何成员.


class Customer1(val cname:String):Customer(cname){
}

class Cusomer2:Customer{
    constructor(cname : String):super(cname)

    constructor(cname : String, age:Int):super(cname)

   final  override fun v() {//可加 final  后 子类不重写
        super.v()
    }

//    你也可以使用一个 var 属性覆盖一个 val 属性, 但不可以反过来使用一个 val 属性覆盖一个 var 属性.
//    允许这种覆盖的原因是, val 属性本质上只是定义了一个 get 方法, 使用 var 属性来覆盖它, 只是向后代类
//    中添加了一个 set 方法.
     override var x: Int
        get() = super.x*2
        set(value) {
           x = value*2
        }

}




interface Foo{
    val count:Int
}

class Bar1(override val count: Int):Foo{

}

class Bar2 :Foo{
//    override val count: Int
//        get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
 override var count: Int =0
}

//在 Kotlin 中, 类继承中的方法实现问题, 遵守以下规则: 如果一个类从它的直接超类中继承了同一个成员的
//多个实现, 那么这个子类必须覆盖这个成员, 并提供一个自己的实现(可以使用继承得到的多个实现中的某一
//个). 为了表示使用的方法是从哪个超类继承得到的, 我们使用 super 关键字, 将超类名称放在尖括号类, 比
//如, super<Base> :


open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}
interface B {
   open fun f() { print("B") } // 接口的成员默认是 'open' 的
    fun b() { print("b") }
}
class C() : A(), B {
    // 编译器要求 f() 方法必须覆盖:
    override fun f() {
        super<A>.f()
        super<B>.f()
    }
}

abstract class D :A(){
    override abstract  fun f()
}

//Kotlin 的类没有静态方法(static method). 大

//封闭类(Sealed class)用来表示对类阶层的限制, 可以限定一个值只允许是某些指定的类型之一, 而不允许是
//其他类型. 感觉上, 封闭类是枚举类(enum class)的一种扩展: 枚举类的值也是有限的, 但每一个枚举值常数
//都只存在唯一的一个实例, 封闭类则不同, 它允许的子类类型是有限的, 但子类可以有多个实例, 每个实例都
//可以包含它自己的状态数据.

//封闭类可以有子类, 但所有的子类声明都必须嵌
//套在封闭类的声明部分之内.
sealed class Expr{
    class Const(val number:Double):Expr()
    class  Sum(val e1:Expr,val  e2:Expr):Expr()
    object  NotANumber:Expr()
}

//从封闭类的子类再继承的子类(间接继承者)可以放在任何地方, 不必在封闭类的声明部分之内.
fun eval(expr: Expr) :Double=when(expr){
    is Expr.Const->expr.number
    is Expr.Sum-> eval(expr.e1)+ eval(expr.e2)
    Expr.NotANumber-> Double.NaN
// 不需要 `else` 分支, 因为我们已经覆盖了所有的可能情况
}